#pragma once
#include<iostream>
#include<functional>
#include<unordered_map>
#include "RingQueue.hpp"
#include<pthread.h>
#include "Thread.hpp"
#include<cstring>
#include "err.hpp"
#include "LockGuard.hpp"
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h> // 必须添加这个来定义 struct sockaddr_in
#include <arpa/inet.h>  // 可选，但推荐添加，用于地址转换函数


using namespace std;

namespace ydd_srver
{
    const static uint16_t default_port = 8080;
    using func_t  = function<string(string)>;

    class UdpServer
    {

    public:
        UdpServer(uint16_t port = default_port):port_(port)
        {
            cout<<"server addr: "<<port_<<endl;
            pthread_mutex_init(&lock,nullptr);

            p = new Thread(1,bind(&UdpServer::Recv,this));
            c = new Thread(1,bind(&UdpServer::Broadcast,this));

        }

        void start()
        {
            //1、创建通信接口，打开一个网络文件
            sock_ = socket(AF_INET,SOCK_DGRAM,0);//成功返回一个fd文件描述符
            if(sock_ < 0 )
            {
                cerr<<"creat socket error: "<<errno<<" :"<<strerror(errno)<<endl;
                exit(SOCKET_ERR);
            }
            cout<<"creat socket success: "<<sock_<<endl;

            //2、给服务器指明ip地址和port号
            struct sockaddr_in local;
            bzero(&local,sizeof(local));

            local.sin_family = AF_INET;
            local.sin_port = htons(port_);
            
            local.sin_addr.s_addr = INADDR_ANY;//可以和任意的ip地址bind，这条指令是将其变为0.0.0.0

            if(bind(sock_,(struct sockaddr *)&local,sizeof(local)) < 0)
            {
                cerr<<"bind socket error: "<<errno<<" :"<<strerror(errno)<<endl;
                exit(BIND_ERR);
            }
            cout<<"creat socket success: "<<sock_<<endl;

            p->run();
            c->run();

        }

        void addUser(const string &name,const struct sockaddr_in &peer)
        {
            LockGuard lockguard(&lock);
            auto iter = onlineuser.find(name);
            if(iter != onlineuser.end()) return;
            onlineuser.insert(pair<const string,const struct sockaddr_in>(name,peer));
        }

        //处理收到的信息
        // string server_(string mess,int len )
        // {
        //     //mess[len] = '#';
        //     mess += "处理中-处理完";
            
        //     return mess;
        // }

        void Recv()
        {
            char buffer[1024];
            while(true)
            {
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                int n = recvfrom(sock_, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
                if (n > 0)
                    buffer[n] = 0;
                else
                    continue;

                //提取client的信息
                string client_ip =  inet_ntoa(peer.sin_addr);
                uint16_t client_port = ntohs(peer.sin_port);
                cout<< client_ip<<"-"<<client_port<<"#"<<buffer<<endl;

                //构建一个用户，并检查
                string name = client_ip;
                name += "-";
                name += to_string(client_port);

                //如果不存在，就插入，如果存在，什么都不做
                addUser(name,peer);
                rq.push(buffer);

                //收到client信息，进行处理
                //string message = server_(buffer);
               // cout<<"收到client信息,进行处理##"<<message<<endl;
                
                //sendto(sock_,message.c_str(),message.size(),0,(struct sockaddr*)&peer,sizeof(peer));

            }

        }
         void Broadcast()
        {
               while (true)
            {
                std::string sendstring;
                rq.pop(&sendstring);

                std::vector<struct sockaddr_in> v;
                {
                    LockGuard lockguard(&lock); // 这个地方不是最优方式
                    for (auto user : onlineuser)
                    {
                        v.push_back(user.second);
                    }
                }
                for (auto user : v)
                {
                    //string message = server_(sendstring);
                    
                     std::cout<<user.sin_port<< "#Broadcast message to 1"  << std::endl;
                    sendto(sock_,sendstring.c_str(), sendstring.size(), 0, (struct sockaddr *)&(user), sizeof(user));
                    //std::cout << "send done ..." << sendstring << std::endl;
                     std::cout<<user.sin_port<< "#Broadcast message to 2"  << std::endl;

                    //std::cout <<sendstring << std::endl;
                }
            }
        }

        ~UdpServer()
        {
            pthread_mutex_destroy(&lock);
            c->join();
            p->join();

            delete c;
            delete p;

        }


    private:
        int sock_;
        uint16_t port_;
        unordered_map<string, struct sockaddr_in> onlineuser;
        pthread_mutex_t lock;
        RingQueue<string> rq;
        //func_t server_;
        Thread *c;
        Thread *p;
    };


}

// namespace ydd_srver
// {
//     const static uint16_t default_port = 8080;
//     using func_t  = function<string(string)>;

//     class UdpServer
//     {

//     public:
//         UdpServer(func_t cd,uint16_t port = default_port):server_(cd),port_(port)
//         {
//             cout<<"server addr: "<<port_<<endl;
//             pthread_mutex_init(&lock,nullptr);

//             p = new Thread(1,bind(&UdpServer::Recv,this));
//             c = new Thread(1,bind(&UdpServer::Broadcast,this));

//         }

//         void start()
//         {
//             //1、创建通信接口，打开一个网络文件
//             sock_ = socket(AF_INET,SOCK_DGRAM,0);//成功返回一个fd文件描述符
//             if(sock_ < 0 )
//             {
//                 cerr<<"creat socket error: "<<errno<<" :"<<strerror(errno)<<endl;
//                 exit(SOCKET_ERR);
//             }
//             cout<<"creat socket success: "<<sock_<<endl;

//             //2、给服务器指明ip地址和port号
//             struct sockaddr_in local;
//             bzero(&local,sizeof(local));

//             local.sin_family = AF_INET;
//             local.sin_port = htons(port_);
            
//             local.sin_addr.s_addr = INADDR_ANY;//可以和任意的ip地址bind，这条指令是将其变为0.0.0.0

//             if(bind(sock_,(struct sockaddr *)&local,sizeof(local)) < 0)
//             {
//                 cerr<<"bind socket error: "<<errno<<" :"<<strerror(errno)<<endl;
//                 exit(BIND_ERR);
//             }
//             cout<<"creat socket success: "<<sock_<<endl;

//             p->run();
//             c->run();

//         }

//         void addUser(const string &name,const struct sockaddr_in &peer)
//         {
//             LockGuard lockguard(&lock);
//             auto iter = onlineuser.find(name);
//             if(iter != onlineuser.end()) return;
//             onlineuser.insert(pair<const string,const struct sockaddr_in>(name,peer));
//         }

//         //处理收到的信息
//         // string server_(string mess,int len )
//         // {
//         //     //mess[len] = '#';
//         //     mess += "处理中-处理完";
            
//         //     return mess;
//         // }

//         void Recv()
//         {
//             char buffer[1024];
//             while(true)
//             {
//                 struct sockaddr_in peer;
//                 socklen_t len = sizeof(peer);
//                 int n = recvfrom(sock_, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
//                 if (n > 0)
//                     buffer[n] = 0;
//                 else
//                     continue;

//                 //提取client的信息
//                 string client_ip =  inet_ntoa(peer.sin_addr);
//                 uint16_t client_port = ntohs(peer.sin_port);
//                 cout<< client_ip<<"-"<<client_port<<"#"<<buffer<<endl;

//                 //构建一个用户，并检查
//                 string name = client_ip;
//                 name += "-";
//                 name += to_string(client_port);

//                 //如果不存在，就插入，如果存在，什么都不做
//                 addUser(name,peer);
//                 rq.push(buffer);

//                 //收到client信息，进行处理
//                 //string message = server_(buffer);
//                // cout<<"收到client信息,进行处理##"<<message<<endl;
                
//                 //sendto(sock_,message.c_str(),message.size(),0,(struct sockaddr*)&peer,sizeof(peer));

//             }

//         }
//          void Broadcast()
//         {
//                while (true)
//             {
//                 std::string sendstring;
//                 rq.pop(&sendstring);

//                 std::vector<struct sockaddr_in> v;
//                 {
//                     LockGuard lockguard(&lock); // 这个地方不是最优方式
//                     for (auto user : onlineuser)
//                     {
//                         v.push_back(user.second);
//                     }
//                 }
//                 for (auto user : v)
//                 {
//                     string message = server_(sendstring);
                    
//                      std::cout << "Broadcast message to 1"  << std::endl;
//                     sendto(sock_, message.c_str(), message.size(), 0, (struct sockaddr *)&(user), sizeof(user));
//                     //std::cout << "send done ..." << sendstring << std::endl;
//                      std::cout << "Broadcast message to 2"  << std::endl;

//                     //std::cout <<sendstring << std::endl;
//                 }
//             }
//         }

//         ~UdpServer()
//         {
//             pthread_mutex_destroy(&lock);
//             c->join();
//             p->join();

//             delete c;
//             delete p;

//         }


//     private:
//         int sock_;
//         uint16_t port_;
//         unordered_map<string, struct sockaddr_in> onlineuser;
//         pthread_mutex_t lock;
//         RingQueue<string> rq;
//         func_t server_;
//         Thread *c;
//         Thread *p;
//     };


// }